import { ProjectActions, ProjectActionTypes } from '../actions/projects.action';
import { Project } from '../domain/index';
import * as _ from 'lodash';
import { createSelector } from '@ngrx/store';

export interface State {
    ids: string[];
    entities: { [id: string]: Project };
    selectedId: string | null;
}

const initialState: State = {
    ids: [],
    entities: {},
    selectedId: null
};

const addProject = (state, action) => {
    const project = action.payload;
    // 如果存在该project 则不添加
    if (state.entities[project.id]) {
        return state;
    }
    // 如果不存在 则在 ids 中添加 project.id
    const ids = [...state.ids, project.id];
    // 在entities 中添加项目
    const entities = { ...state.entities, [project.id]: project };
    return { ...state, ids, entities };
};

const updateProject = (state, action) => {
    const project = action.payload;
    // 替换
    const entities = { ...state, [project.id]: project };
    return { ...state, entities };
};
const delProject = (state, action) => {
    const project = action.payload;
    console.log('a', state.ids);
    const newIds = state.ids.filter(id => id !== project.id);
    const stateEntities = state.entities;
    const newEntities = newIds.reduce((entities, id: string) => ({ ...entities, [id]: stateEntities[id] }), {});
    return { ids: newIds, entities: newEntities, selectedId: null };
};
// 加载新数据， 如果存在则不添加，如果不存在则添加进去，方便进行分页
const loadProject = (state, action) => {
    const projects = action.payload; // 这里返回的是个数组
    const inComingIds = projects.map(p => p.id); // 获取传进来的所有id
    const newIds = _.difference(inComingIds, state.ids); // 获取两个数组的超集
    // 获取一个新的字典(对象) keyBy: 列表对象中的id 最为新对象的key 对象为值
    const inComingEntities = _.chain(projects).keyBy('id').mapValues(o => o).value();
    const newEntities = newIds.reduce((entities, id: string) => ({ ...entities, [id]: inComingEntities[id] }), {});
    return {
        ids: [...state.ids, ...newIds],
        entities: { ...state.entities, ...newEntities },
        selectedId: null
    };
};


export function reducer(state = initialState, action: ProjectActions): State {
    switch (action.type) {
        case ProjectActionTypes.ADD_SUCCESS: {
            return addProject(state, action);
        }
        case ProjectActionTypes.DELETE_SUCCESS: {
            return delProject(state, action);
        }
        case ProjectActionTypes.INVITE_SUCCESS:
        case ProjectActionTypes.UPDATE_SUCCESS: {
            return updateProject(state, action);
        }
        case ProjectActionTypes.LOAD_SUCCESS: {
            return loadProject(state, action);
        }
        case ProjectActionTypes.SELECT_PROJECT: {
            return { ...state, selectedId: action.payload.id };
        }
        default: {
            return state;
        }
    }
}

export const getIds = (state: State) => state.ids;
export const getEntities = (state: State) => state.entities;
export const getSelectedId = (state: State) => state.selectedId;

export const getAll = createSelector(getIds, getEntities, (ids, entities) => {
    return ids.map(key => entities[key]);
});
